package com.mo.lib.utils.data

import kotlin.math.roundToInt


/**
 * @ author：mo
 * @ data：2021/1/14:11:48
 * @ 功能：
 * WGS84：谷歌地图，地球坐标系，国际通用坐标系。设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系
 * GCJ02  ：谷歌中国地图、高德地图、腾讯地图，火星坐标系，是由国测局（中国国家测绘局）制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系
 * BD09   ：百度地图，GCJ02坐标系经加密后的坐标系
 */
const val pi = 3.1415926535897932384626
const val a = 6378245.0
const val ee = 0.00669342162296594323
const val x_pi = 3.14159265358979324 * 3000.0 / 180.0


/** 谷歌 转 高德*/
fun googleToGd(lat: Double, lon: Double) = wgs2gcj(lat, lon)

/** 谷歌 转 百度*/
fun googleToBd(lat: Double, lon: Double) = wgs2bd(lat, lon)

/** 高德 转 百度*/
fun gdToBd(lat: Double, lon: Double) = gcj2bd(lat, lon)

/** 百度 转 高德*/
fun bdToGd(lat: Double, lon: Double) = bd2gcj(lat, lon)

/** GCJ02 转 BD09*/
fun gcj2bd(lat: Double, lon: Double): DoubleArray {
    val z = Math.sqrt(lon * lon + lat * lat) + 0.00002 * Math.sin(lat * x_pi)
    val theta = Math.atan2(lat, lon) + 0.000003 * Math.cos(lon * x_pi)
    val bd_lon = z * Math.cos(theta) + 0.0065
    val bd_lat = z * Math.sin(theta) + 0.006
    return doubleArrayOf(bd_lat, bd_lon)
}

/** BD09 转 GCJ02*/
fun bd2gcj(lat: Double, lon: Double): DoubleArray {
    val x = lon - 0.0065
    val y = lat - 0.006
    val z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi)
    val theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi)
    val gg_lon = z * Math.cos(theta)
    val gg_lat = z * Math.sin(theta)
    return doubleArrayOf(gg_lat, gg_lon)
}

/** WGS84 转 GCJ02*/
fun wgs2gcj(lat: Double, lon: Double): DoubleArray {
    var dLat = transformLat(lon - 105.0, lat - 35.0)
    var dLon = transformLon(lon - 105.0, lat - 35.0)
    val radLat = lat / 180.0 * pi
    var magic = Math.sin(radLat)
    magic = 1 - ee * magic * magic
    val sqrtMagic = Math.sqrt(magic)
    dLat = dLat * 180.0 / (a * (1 - ee) / (magic * sqrtMagic) * pi)
    dLon = dLon * 180.0 / (a / sqrtMagic * Math.cos(radLat) * pi)
    val mgLat = lat + dLat
    val mgLon = lon + dLon
    return doubleArrayOf(mgLat, mgLon)
}

/** WGS84 转 BD09*/
fun wgs2bd(lat: Double, lon: Double): DoubleArray {
    val wgs2gcj = wgs2gcj(lat, lon)
    return gcj2bd(wgs2gcj[0], wgs2gcj[1])
}

private fun transformLat(lat: Double, lon: Double): Double {
    var ret = -100.0 + 2.0 * lat + 3.0 * lon + 0.2 * lon * lon + 0.1 * lat * lon + 0.2 * Math.sqrt(Math.abs(lat))
    ret += (20.0 * Math.sin(6.0 * lat * pi) + 20.0 * Math.sin(2.0 * lat * pi)) * 2.0 / 3.0
    ret += (20.0 * Math.sin(lon * pi) + 40.0 * Math.sin(lon / 3.0 * pi)) * 2.0 / 3.0
    ret += (160.0 * Math.sin(lon / 12.0 * pi) + 320 * Math.sin(lon * pi / 30.0)) * 2.0 / 3.0
    return ret
}

private fun transformLon(lat: Double, lon: Double): Double {
    var ret = 300.0 + lat + 2.0 * lon + 0.1 * lat * lat + 0.1 * lat * lon + 0.1 * Math.sqrt(Math.abs(lat))
    ret += (20.0 * Math.sin(6.0 * lat * pi) + 20.0 * Math.sin(2.0 * lat * pi)) * 2.0 / 3.0
    ret += (20.0 * Math.sin(lat * pi) + 40.0 * Math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
    ret += (150.0 * Math.sin(lat / 12.0 * pi) + 300.0 * Math.sin(lat / 30.0 * pi)) * 2.0 / 3.0
    return ret
}

/** 纬度在前，经度在后*/
fun getLoctionDowble(lat: Double, lon: Double): DoubleArray{
    return if (lat.roundToInt() > lon.roundToInt()) {
        doubleArrayOf(lon, lat)
    } else {
        doubleArrayOf(lat, lon)
    }
}
